package opf5.persistencia.proxies;

import java.util.List;

import opf5.entities.dominio.Equipo;
import opf5.entities.dominio.Inscripcion;
import opf5.entities.dominio.Jugador;
import opf5.entities.dominio.Partido;
import opf5.entities.jugadores.JugadorConcreto;
import opf5.entities.notificaciones.PartidoNotificadorCompletoDecorator;
import opf5.entities.notificaciones.PartidoNotificadorIncompletoDecorator;
import opf5.entities.notificaciones.PartidoNotificadorInscripcionDecorator;
import opf5.entities.partidos.EstadoEquiposConfirmados;
import opf5.entities.partidos.EstadoInscripcionesAbiertas;
import opf5.entities.partidos.EstadoPartido;
import opf5.entities.partidos.EstadoPartidoTerminado;
import opf5.entities.partidos.PartidoConcreto;
import opf5.persistencia.OPF5DBGateway;
import opf5.utilidades.EnviadorDeEmail;
import opf5.utilidades.EnviadorDeEmailImprimir;
import opf5.utilidades.Fecha;

public class PartidoDBProxy implements Partido {
	private Partido partidoConcreto;
	private int id;

	private boolean inscripcionesCargadas = false;
	
	public PartidoDBProxy() {
		Jugador admin = new JugadorConcreto("admin", "admin@opf5.com", new Fecha());
		
		EnviadorDeEmail enviador = new EnviadorDeEmailImprimir();
		Partido partido =  new PartidoConcreto(null, null);
		
		partido = new PartidoNotificadorCompletoDecorator(partido, enviador, admin);
		partido = new PartidoNotificadorIncompletoDecorator(partido, enviador, admin);
		partido = new PartidoNotificadorInscripcionDecorator(partido, enviador);

		this.partidoConcreto = partido;
	}
	
	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public PartidoDBProxy(Partido partido) {
		this.partidoConcreto = partido;
	}

	@Override
	public int cantidadJugadoresInscriptos() {
		cargarInscripciones();
		return this.partidoConcreto.cantidadJugadoresInscriptos();
	}

	private void cargarInscripciones() {
		if (! inscripcionesCargadas) {
			this.setInscripciones(OPF5DBGateway.getInscripcionesPartido(this));
			this.inscripcionesCargadas = true;
		}
	}

	@Override
	public boolean estaInscripto(Jugador unJugador) {
		cargarInscripciones();
		return this.partidoConcreto.estaInscripto(unJugador);
	}

	@Override
	public boolean hayLugar() {
		cargarInscripciones();
		return this.partidoConcreto.hayLugar();
	}

	@Override
	public List<Inscripcion> getInscripciones() {
		cargarInscripciones();
		return this.partidoConcreto.getInscripciones();
	}

	@Override
	public List<Equipo> getEquipos() {
		return this.partidoConcreto.getEquipos();
	}

	@Override
	public int[] getResultados() {
		return this.partidoConcreto.getResultados();
	}

	@Override
	public Fecha getFechaPartido() {
		return this.partidoConcreto.getFechaPartido();
	}

	@Override
	public String getLugar() {
		return this.partidoConcreto.getLugar();
	}

	@Override
	public EstadoPartido getEstado() {
		return this.partidoConcreto.getEstado();
	}

	@Override
	public boolean estaTerminado() {
		return this.partidoConcreto.estaTerminado();
	}

	@Override
	public void inscribir(Inscripcion nuevaInscripcion) {
		cargarInscripciones();
		
		this.partidoConcreto.inscribir(nuevaInscripcion);
		OPF5DBGateway.agregarInscripcionAPartido(this, (InscripcionDBProxy) nuevaInscripcion);
		
		if (this.partidoConcreto.getInscripciones().size() == 10) {
			for (Inscripcion i : OPF5DBGateway.getInscripcionesPartido(this)) {
				if (! this.estaInscripto(i.getJugador()))
					OPF5DBGateway.removerInscripcion(this, (InscripcionDBProxy) i);
			}
		}
	}

	@Override
	public void setLugarPartido(String lugar) {
		this.partidoConcreto.setLugarPartido(lugar);
		OPF5DBGateway.guardarPartido(this);
	}

	public void setLugar(String lugar) {
		this.partidoConcreto.setLugarPartido(lugar);
	}
	
	@Override
	public void setFechaPartido(Fecha fecha) {
		this.partidoConcreto.setFechaPartido(fecha);
		OPF5DBGateway.guardarPartido(this);
	}

	public void setFecha(String fecha) {
		this.partidoConcreto.setFechaPartido(new Fecha(fecha, "yyyy-MM-dd HH:mm"));
	}
	
	@Override
	public void setResultado(int golesEquipo1, int golesEquipo2) {
		this.partidoConcreto.setResultado(golesEquipo1, golesEquipo2);
		OPF5DBGateway.guardar(this);
	}

	@Override
	public void confirmarEquipos(Equipo equipo1, Equipo equipo2) {
		this.partidoConcreto.confirmarEquipos(equipo1, equipo2);
		OPF5DBGateway.agregarEquipos(this, (EquipoDBProxy)equipo1, (EquipoDBProxy)equipo2);
	}

	@Override
	public void darDeBajaSinReemplazo(Jugador unJugador) {
		InscripcionDBProxy i = this.getInscripcion(unJugador);
		this.partidoConcreto.darDeBajaSinReemplazo(unJugador);
		OPF5DBGateway.removerInscripcion(this, i);
	}

	private InscripcionDBProxy getInscripcion(Jugador unJugador) {
		cargarInscripciones();
		for (Inscripcion i : this.partidoConcreto.getInscripciones()) {
			if (i.getJugador().equals(unJugador))
				return (InscripcionDBProxy) i;
		}
		
		return null;
	}

	@Override
	public void darDeBajaConReemplazo(Jugador unJugador, Jugador otroJugador) {
		cargarInscripciones();
		InscripcionDBProxy i = this.getInscripcion(unJugador);
		this.partidoConcreto.darDeBajaConReemplazo(unJugador, otroJugador);
		OPF5DBGateway.removerInscripcion(this, i);
		OPF5DBGateway.agregarInscripcionAPartido(this, getInscripcion(otroJugador));
	}
	
	public String getEstadoPartido() {
		return this.partidoConcreto.getEstado().toString();
	}
	
	public void setEstadoPartido(String estadoString) {
		if (estadoString.equals("Inscripciones abiertas"))
			this.partidoConcreto.setEstado(new EstadoInscripcionesAbiertas());
		else if (estadoString.equals("Equipos Confirmados"))
			this.partidoConcreto.setEstado(new EstadoEquiposConfirmados());
		else if (estadoString.equals("Terminado"))
			this.partidoConcreto.setEstado(new EstadoPartidoTerminado());
	}
	
	public String getFecha() {
		return this.partidoConcreto.getFechaPartido().toString();
	}

	@Override
	public void setEstado(EstadoPartido estado) {
		this.partidoConcreto.setEstado(estado);
		OPF5DBGateway.guardarPartido(this);
	}

	@Override
	public void setInscripciones(List<Inscripcion> inscripciones) {
		this.partidoConcreto.setInscripciones(inscripciones);		
	}
	
	public int getIdEquipo1() {
		try {
			return ((EquipoDBProxy) this.partidoConcreto.getEquipos().get(0)).getIdEquipo();
		} catch (Exception e) {
			return 0;
		}
	}

	public int getIdEquipo2() {
		try {
			return ((EquipoDBProxy) this.partidoConcreto.getEquipos().get(1)).getIdEquipo();
		} catch (Exception e) {
			return 0;
		}
	}
	
	public void setIdEquipo1(int i) {
		if (i != 0)
			this.partidoConcreto.setEquipo(0, OPF5DBGateway.getEquipo(i));
	}
	
	public void setIdEquipo2(int i) {
		if (i != 0)
			this.partidoConcreto.setEquipo(1, OPF5DBGateway.getEquipo(i));
	}

	@Override
	public void setEquipo(int numero, Equipo equipo) {
		this.partidoConcreto.setEquipo(numero, equipo);
	}
	
	@Override
	public boolean equals(Object o) {
		return this.id == ((PartidoDBProxy) o).getId();
	}
}
